from fastapi import APIRouter, Depends, HTTPException, status, Body, Path

from recruit.domain.exceptions.user import (
    UserExistsError,
    UserNotFoundException,
)
from recruit.domain.models.user import (
    UserResult,
    UserCreate,
    UserUpdate,
    UserUpdateDTO,
)
from recruit.domain.models.user_id import UserId, UserTelegramId
from recruit.presentation.openapi.create_user import (
    BODY_USER_CREATE_EXAMPLE,
    RESPONSE_USER_CREATE_EXAMPLE,
)
from recruit.presentation.openapi.get_user import RESPONSE_USER_GET_EXAMPLE
from recruit.presentation.openapi.update_user import (
    RESPONSE_USER_UPDATE_EXAMPLE, BODY_USER_UPDATE_EXAMPLE,
)
from recruit.presentation.user_interactor import UserInteractorFactory

router = APIRouter(prefix='/api/users', tags=['Users'])


@router.post(
    '/',
    name='Создание пользователя',
    response_model=UserResult,
    status_code=status.HTTP_201_CREATED,
    responses=RESPONSE_USER_CREATE_EXAMPLE
)
async def create_user(
        user: UserCreate = Body(
            ...,
            example=BODY_USER_CREATE_EXAMPLE
        ),
        ioc: UserInteractorFactory = Depends()
):
    try:
        async with ioc.create_user() as create_user_interactor:
            return await create_user_interactor(user)
    except UserExistsError as error:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(error)
        )


@router.get(
    '/{user_id}/',
    name='Получение пользователя',
    response_model=UserResult,
    responses=RESPONSE_USER_GET_EXAMPLE
)
async def get_user(
        user_id: UserTelegramId = Path(
            ...,
            description='Уникальный идентификатор пользователя'
        ),
        ioc: UserInteractorFactory = Depends()
):
    try:
        async with ioc.get_user() as get_user_interactor:
            return await get_user_interactor(user_id)
    except UserNotFoundException as error:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=str(error)
        )


@router.patch(
    '/{user_id}/',
    name='Обновления данных пользователя',
    response_model=UserResult,
    responses=RESPONSE_USER_UPDATE_EXAMPLE
)
async def update_user(
        user_id: UserId = Path(
            ...,
            description='Уникальный идентификатор пользователя'
        ),
        user: UserUpdate = Body(
            ...,
            example=BODY_USER_UPDATE_EXAMPLE
        ),
        ioc: UserInteractorFactory = Depends()
):
    try:
        async with ioc.update_user() as update_user_interactor:
            return await update_user_interactor(
                UserUpdateDTO(
                    id=user_id,
                    **user.model_dump()
                )
            )
    except UserNotFoundException as error:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=str(error)
        )
